<template>
  <div>
    <!-- header start -->
    <el-row class="sea-table-header">
      <!-- form-header -->
      <el-col :span="box_layout[0]">

        <!-- header-title -->
        <slot name="title"></slot>

        <!-- quick-search -->
        <el-form @submit.native.prevent="onSubmit" :size="props.size" style="display: inline-block;" class="margin-bottom">
          <el-input v-model="keyword" placeholder="请输入内容"
                    style="width: 200px;margin-right: 12px;"
                    :size="props.size">
            <template #append>
              <el-button @click="onSubmit" :loading="loading">
                <i class="fa fa-search"></i>
              </el-button>
            </template>
          </el-input>
        </el-form>

        <!-- buttons -->
        <slot name="buttons"></slot>
      </el-col>

      <!-- 拓展表单-->
      <el-col :span="box_layout[1]" v-if="enabled_form">
        <div style="width: calc(100% - 72px);float: left;">
          <el-row>
            <el-form ref="form" :model="props.params" v-show="expand" :inline="true">

              <!-- form-input -->
              <slot name="input"></slot>

              <el-form-item>
                <el-button size="small" type="primary" @click="onSubmit" :loading="loading">查询</el-button>
                <el-button size="small" @click="onReset" :loading="loading">重置</el-button>
              </el-form-item>
            </el-form>
          </el-row>
        </div>

        <!-- expand-button -->
        <div style="width: 72px;float: right;">
          <el-button size="small" title="展开" @click="switchExpand">
            <i :class="expand? 'fa fa-chevron-up' : 'fa fa-chevron-down'"></i>
          </el-button>
        </div>
      </el-col>
    </el-row>
    <!-- header end -->

    <!-- body -->
    <el-row v-loading="loading">
      <el-col>
        <slot :list="list"></slot>
      </el-col>
    </el-row>
    <!-- body -->
  </div>
</template>

<script setup>
/* eslint-disable */
import {ref, watch, onMounted} from "vue";
import Layers from "@/lang/layers/index";
import setting from "@/widget/provider/setting";

/**
 * 搜索栏
 *
 * sea-net-frame 禁用分页与当前效果完全一致，这个组件只是去除了分页部分的设计，
 *
 * 这个封装完全是为了组件专项专用，避免毫无意义的性能浪费。
 */
const props = defineProps({
    // 数据 url
    url: {type: String, default: undefined},
    // 请求方式
    method: {type: String, default: 'GET'},
    // 响应式参数，值的改变会触发查询
    where: {type: Object, default: undefined},
    // 表单默认值，首次查询所需的参数（改变不会触发查询）
    params: {type: Object, default: undefined},

    // 本地数据，直接指定数据列表
    data: {type: Array, default: undefined},

    // 触发器，数据联动逻辑
    trigger: {type: Function, default: undefined},
    // 按钮组件大小
    size: {type: String, default: 'default'},

    // 禁用表单
    disabledForm: {type: Boolean, default: false},
    // 表单模型
    model: {type: Array, default: undefined},

    // 挂载后自动触发查询
    autoLoad: {type: Boolean, default: true},
    // 数据查询执行器
    provider: {type: Function, default: setting.ajax},
    // 查询结果格式化
    resultParser: {type: Function, default: setting.paginationParser},

    // 提交表单前置拦截，如果不满足条件，可以阻止表单提交
    intercept: {type: Function, default: undefined},
    // 表格数据后置处理，可能要进行格式转换啥的
    afterQuery: {type: Function, default: undefined},

    // 快速检索：启用之后，不会从后台加载数据，而是从静态数据中直接进行检索过滤
    quickSearch: {type: Boolean, default: false},
    // 快速检索：检索函数
    searchMethod: {type: Function, default: setting.search}
});

// 展开表单
const expand = ref(false);
// 表格数据加载中
const loading = ref(false);

// 关键字
const keyword = ref('');

// 数据列表，用于记录原始值
let original_list = props.data;
// 数据列表，通过插槽回传数据
const list = ref(original_list);

// 默认值
const default_value = {};

// 绑定联动的参数
let query_where = props.params || {};
// 表单初始值
let query_params = props.where ||  {};

// 表单初值
const box_layout = ref([6, 18]);
const enabled_form = ref(false);
if(props.params === undefined){
    // 布局
    box_layout.value = [24, 0];
    enabled_form.value = true;

    // 默认值
    Layers.assign(props.params, default_value);
}


/**
 * 首次载入数据
 *
 * 首次加载是非常特殊的，
 * 需要获取分页、表单等各方的初始化数据，
 * 这些数据分布在各个插槽中，
 *
 * 插槽中的组件，生命周期是不可控的，在调用这个函数的时候，组件可能还没渲染完成，
 *
 * 因此这个函数很容易产生空指针异常，写法上，尽量保证所有数据载入完成。
 */
const firstLoad = () => {
    if (props.autoLoad && Layers.isNotEmpty(props.url)) {
        reload();
    }
};


/**
 * 重新载入数据
 *
 * @param values 参数
 */
const reload = (values) => {
    // 正在加载
    if (loading.value) {
        return;
    }
    loading.value = true;

    // 构建请求参数
    let params = {};

    // 表单参数
    Layers.assign(query_params, params);
    // 额外指定的参数
    Layers.assign(query_where, params);
    // 微调参数
    Layers.assign(values, params);

    let request = {
        url: props.url,
        method: props.method,
        params: params
    }

    // 前置拦截，进行逻辑判断，根据内容决定是否提交
    if (props.intercept !== undefined && props.intercept(request) === false) {
        return;
    }

    // ajax参数
    props.provider(request).then(response => {
        let resp = props.resultParser(response);

        if (props.afterQuery === undefined) {
            original_list = resp.list;
            list.value = resp.list;
        } else {
            // 数据后置处理，如果有返回值，则使用返回值
            let ret = props.afterQuery(ret.list);
            if (ret === undefined) {
                original_list = resp.list;
                list.value = resp.list;
            } else {
                original_list = ret;
                list.vlaue = ret;
            }
        }
    }).finally(() => {
        loading.value = false;
    })
}

/**
 * 表单数据发生变化，并触发查询
 *
 * @param params 表单数据
 */
const handlerParams = (params) => {
    query_params = params;
    reload();
};

/**
 * 触发查询，附加参数发生变化
 *
 * @param where 附加参数
 */
const handlerWhere = (where) => {
    query_where = where;
    reload();
};

/**
 * 设置表单数据，不触发查询
 *
 * @param params 表单数据
 */
const setParams = (params) => {
    query_params = params;
};

/**
 * 设置附加数据，不触发查询
 *
 * @param where 附加参数
 */
const setWhere = (where) => {
    query_where = where;
};


/**
 * 展开搜索栏，默认搜索栏处于隐藏状态
 */
const switchExpand = () => {
    expand.value = !expand.value;
};

/**
 * 点击了提交按钮
 */
const onSubmit = () => {
    let key = keyword.value;
    if(props.quickSearch && Layers.isNotEmpty(key)){
        list.value = props.searchMethod(original_list, key);
    } else {
        // 获取服务器的数据
        query_params.keyword = keyword.value;
        reload();
    }
};

/**
 * 点击了重置按钮
 */
const onReset = () => {
    Layers.assign(default_value, query_params);
    reload();
};

// Watchers 每一个侦听，触发的时候都会刷新表格
watch(() => props.where, handlerWhere);

// 首次加载数据
onMounted(firstLoad);

</script>